#ifndef BASE_H
#define BASE_H

#include <stdexcept>

#include <QList>

template <class T>
class List : public QList<T>
{
public:
    // Constructors
    List() : QList<T>(){}
    List(const List<T> &other) : QList<T>(other) {}
    List(const QList<T> &other) : QList<T>(other) {}

    List<T> operator *(int times)
    {
        //Repeat the list for N times.
        List<T> result;
        //Prepare the memory place.
        result.reserve(this->size() * times);
        while(times--)
        {
            //Append single data to result.
            result.append(*this);
        }
        return result;
    }

    const T &at(int i) const
    {
        if(i<0)
        {
            //Update the i.
            i=size()+i;
        }
        // Check the validation of i.
        if(i<0 || i>=size())
        {
            throw std::exception("error!!");
        }
        return (i<0) ? QList<T>::at(size() + i) : QList<T>::at(i);
    }

    const T &operator[](int i) const
    {
        return this->at(i);
    }

    T &operator[](int i)
    {
        if(i<0)
        {
            //Update the i.
            i=size()+i;
        }
        // Check the validation of i.
        if(i<0 || i>=size())
        {
            throw std::exception("error!!");
        }
        return QList<T>::operator[](i);
    }
};

class JObject
{
public:
    JObject(JObject *parent = nullptr)
    {
        if(parent)
        {
            parent->addChild(this);
        }
    }

    virtual ~JObject()
    {
        for(auto object : m_children)
        {
            //Recycle the children.
            delete object;
        }
    }

    void addChild(JObject *children)
    {
        m_children.append(children);
    }

private:
    QList<JObject *> m_children;
};

#endif // BASE_H
